<template>
  <div>
    <el-card shadow="always" :body-style="{ padding: '20px' }">
      <el-form style="margin-bottom: 20px">
        <el-input placeholder="用户名" size="small" clearable style="width: 180px; margin-right: 20px"
          v-model="searchObj.username">
        </el-input>
        <el-button type="primary" size="small" icon="el-icon-search" @click="search">
          查询</el-button>
        <el-button size="small" @click="clear">清空</el-button>
      </el-form>
      <el-button type="primary" size="small" @click="showAdd" v-if="$hasBP('btn.User.add')">添加</el-button>
      <el-button type="danger" size="small" @click="deleteAll" :disabled="selectedId.length === 0">批量删除</el-button>
      <!-- 表格 
        selection-change 当选择项发生变化时会触发该事件
      -->
      <el-table border stripe style="margin-top: 20px" :data="userData.items" @selection-change="changeSelection">
        <el-table-column width="55px" align="center" type="selection">
        </el-table-column>
        <el-table-column label="序号" width="80px" type="index" align="center">
        </el-table-column>
        <el-table-column label="用户名" prop="username" width="150px">
        </el-table-column>
        <el-table-column label="用户昵称" prop="nickName" width="120px">
        </el-table-column>
        <el-table-column label="角色列表" prop="roleName" width="200px" show-overflow-tooltip>
        </el-table-column>
        <el-table-column label="创建时间" prop="gmtCreate" width="180px">
        </el-table-column>
        <el-table-column label="更新时间" prop="gmtModified" width="180px">
        </el-table-column>
        <!--对话框的展示-->
        <el-table-column label="操作" align="center" width="180px" fixed="right">
          <template v-slot="{ row, $index }">
            <!-- 查看按钮 -->
            <el-button type="info" size="mini" icon="el-icon-user-solid" @click="showRole(row)"></el-button>
            <!-- 修改按钮 -->
            <el-button type="primary" size="mini" icon="el-icon-edit-outline" style="margin-right: 10px"
              @click="showUpdate(row)"></el-button>
            <el-popconfirm :title="`确定删除${row.username}吗？`" @confirm="deleteOne(row.id)">
              <!-- 删除按钮 -->
              <el-button type="danger" size="mini" icon="el-icon-delete" slot="reference"></el-button>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页器 -->
      <el-pagination style="margin-top: 20px" @size-change="sizeChange" @current-change="getUserList"
        :current-page.sync="currentPage" :page-sizes="[5, 10, 20, 30]" :page-size="pageSize"
        layout="prev, pager, next, jumper,->,sizes,total" :total="userData.total" background :pager-count="7">
      </el-pagination>
    </el-card>
    <!-- 添加对话框 -->
    <el-dialog :title="user.id ? '修改用户' : '添加用户'" :visible.sync="dialogFormVisible">
      <el-form :model="user" :rules="rules" ref="user">
        <el-form-item label="用户名" label-width="80px" prop="username">
          <el-input v-model="user.username"></el-input>
        </el-form-item>
        <el-form-item label="用户昵称" label-width="80px" prop="nickName">
          <el-input v-model="user.nickName"></el-input>
        </el-form-item>
        <el-form-item label="用户密码" label-width="80px" prop="password">
          <el-input v-model="user.password" type="password"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="addOrUpdateUser">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 设置角色的对话框 -->
    <el-dialog title="设置角色" :visible.sync="dialogFormVisible1">
      <el-form label-width="80px">
        <el-form-item label="用户名" label-width="80px">
          <el-input disabled :value="user.username"></el-input>
        </el-form-item>
        <el-form-item label="角色列表" label-width="80px">
          <!-- 全选框 -->
          <el-checkbox v-model="checkAll" @change="changeCheckedAll" :indeterminate="isIndeterminate">全选</el-checkbox>
          <!-- 角色复选框 -->
          <el-checkbox-group v-model="userRoleIds" @change="changeChecked">
            <!-- 注意label绑定时不要绑定整个表单的 id !!! -->
            <el-checkbox v-for="role in roleList" :label="role.id" :key="role.id">{{ role.roleName }}</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible1 = false">取 消</el-button>
        <el-button type="primary" @click="setRole">保存</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "User",
  data() {
    return {
      // 当前页
      currentPage: 1,
      // 一页展示几条数据
      pageSize: 5,
      // 输入框的内容
      searchObj: { username: "" },
      // 获取服务器返回的用户列表数据
      userData: [],
      // 控制第一个对话框展示或隐藏的变量
      dialogFormVisible: false,
      // 控制第二个对话框展示或隐藏的变量
      dialogFormVisible1: false,

      // 添加新用户需要给服务器传递的请求体数据
      user: { username: "", nickName: "", password: "", id: "" },
      // 需要批量删除的数据数组
      selectedId: [],
      // 角色列表
      roleList: [],
      // 角色列表的id
      userRoleIds: [],
      // 是否全选
      checkAll: false,
      // 非全选和非全不选的状态
      isIndeterminate: false,
      // 表单验证规则
      rules: {
        username: [
          { required: true, message: "请输入品牌名称", trigger: "blur" },
          {
            required: true,
            min: 3,
            max: 6,
            message: "品牌名称在3到6个字之间",
            trigger: "blur",
          },
        ],
        nickName: [{ required: true, message: "LOGO不能为空,请上传图片" }],
        password: [
          { required: true, message: "密码不能为空", trigger: "blur" },
          {
            required: true,
            min: 6,
            max: 8,
            message: "密码长度在6到8个字符之间",
            trigger: "blur",
          },
        ],
      },
    };
  },
  mounted() {
    this.getUserList();
  },
  methods: {
    // 改变每页数据展示条数的回调
    sizeChange(pageSize) {
      this.pageSize = pageSize;
      this.getUserList();
    },
    // 获取用户信息
    async getUserList(currentPage = 1) {
      this.currentPage = currentPage;
      let result = await this.$API.user.getPageList(
        this.currentPage,
        this.pageSize,
        this.searchObj
      );
      this.userData = result.data;
    },
    // 点击查询的回调,因为输入框中的内容在每次输入时都会发生改变,所以使用对象进行存储
    search() {
      if (this.searchObj.username === "") {
        return;
      }
      this.searchObj = { ...this.searchObj };
      this.getUserList();
    },
    // 点击清空的回调
    clear() {
      // 清空数据
      this.searchObj.username = "";
      // 再次获取数据
      this.getUserList();
    },
    // 显示添加用户的对话框
    showAdd() {
      this.user = { username: "", nickName: "", password: "", id: "" };
      this.dialogFormVisible = true;
      this.$nextTick(() => this.$refs.user.resetFields());
    },
    // 显示修改用户的对话框
    showUpdate(row) {
      // 想想有没有更优方案
      this.user = row;
      this.dialogFormVisible = true;
    },
    // 添加/修改用户的回调
    async addOrUpdateUser() {
      // 也可通过解构的方式,这样可以不用在传值的时候写 this了
      // 判断是新增用户还是修改用户,通过 id 来判断,用三元表达式来做,if判断不好添加 async和 await
      await this.$API.user[this.user.id ? "update" : "add"](this.user);
      this.dialogFormVisible = false;
      this.$message.success(this.user.id ? "修改成功" : "添加成功");
      // 再次获取数据
      this.getUserList(this.user.id ? this.currentPage : 1);
      // 清空数据,避免点击修改后再次点击添加,对话框中还有数据
      this.user = { username: "", nickName: "", password: "", id: "" };
    },
    // 监听选中状态的回调
    changeSelection(selection) {
      this.selectedId = selection.map((item) => item.id);
    },
    // 展示角色对话框
    showRole(user) {
      this.user = user;
      this.dialogFormVisible1 = true;
      this.allRole();
    },
    // 监听全部选中状态的回调
    changeCheckedAll(value) {
      this.userRoleIds = value ? this.roleList.map((item) => item.id) : [];
      this.isIndeterminate = false;
    },
    // 监听单个选中状态的回调
    changeChecked(value) {
      const { userRoleIds, roleList } = this;
      this.checkAll =
        userRoleIds.length === roleList.length && roleList.length > 0;
      this.isIndeterminate =
        userRoleIds.length > 0 && userRoleIds.length < roleList.length;
      console.log(this.checkAll, this.isIndeterminate);
    },
    // 获取单个用户的所有角色
    async allRole() {
      let result = await this.$API.user.getRoles(this.user.id);
      // 解构服务器返回的数据
      const { allRolesList, assignRoles } = result.data;
      this.roleList = allRolesList;
      // 角色列表的id
      this.userRoleIds = assignRoles.map((item) => item.id);
      // 全选需要满足:单个用户的所有角色选中个数 === 分配给它的角色个数,相等时即全选
      this.checkAll = allRolesList.length === assignRoles.length;
      // 非全选和非全不选需要满足:分配角色个数大于0 且 选中个数小于所有角色个数
      this.isIndeterminate =
        assignRoles.length > 0 && assignRoles.length < allRolesList.length;
    },
    // 给某个用户分配角色的回调
    async setRole() {
      const userId = this.user.id;
      const roleIds = this.userRoleIds.join(",");
      this.dialogFormVisible1 = false;
      let result = await this.$API.user.assignRoles(userId, roleIds);
      this.$message.success("分配角色成功");
      // 再次获取数据
      this.getUserList();
    },
    // 删除单个用户的回调
    async deleteOne(id) {
      await this.$API.user.removeById(id);
      this.$message.success("删除成功");
      // 再次获取数据
      this.getUserList(
        this.userData.length === 1 && this.currentPage > 1
          ? this.currentPage - 1
          : this.currentPage
      );
    },
    // 批量删除用户的回调
    deleteAll() {
      this.$confirm("确定删除吗?", {})
        .then(async () => {
          // 得接收一下返回值,因为此处是 promise
          let result = await this.$API.user.removeUsers(this.selectedId);
          this.$message.success("批量删除成功");
          // 再次获取请求
          this.getUserList();
        })
        .catch(() => { });
    },
    // 点击取消的回调
    cancel() {
      this.dialogFormVisible = false;
      this.user = {};
      this.getUserList();
    },
    // 表单验证相关回调
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          alert("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
  },
};
</script>

<style scoped>

</style>